/**
 * The Experience class handles the entire leveling system.
 *  
 * The gameobject this class is attached too will be able to gain experience and level up.
 * When a level is gained the remaining experience is added into the new level.
 * A level curve can be defined to make each consecutive level harder to obtain.
 * 
 * When a new level gained the script also searched for an audiosource and plays a sound and graphics effect if
 * the user defined this in the editor.
 *
 * On awaking and on leveling up the class searches for a CharacterStats class and calls methods to update
 * these stats according to the gameobject's new level.
 *
 * Author: Reinier
 */

public var  experience : int = 0;				/* The Experience being tracked */
public var  level : int = 0;					/* The level being tracked, the first level should be 0 for math purposes */
public var  levelCurve : float = 1.5;			/* The level curve for increasing each consecutive's level
												 * max experience, for the exact formula see the SetMaxXP method */
public var  levelMaxExperienceBase : int = 100; /* The base experience for obtaining a new level*/
public var  levelUpParticles : GameObject;		/* A particle system that will be spawned when leveling up */
public var  levelUpSound : AudioClip;			/* An audioclip that will be played when leveling up (TODO the sound is not yet used) */
public var  xpParticles : GameObject;			/* A particle system that will be spawned when gaining experience */

private var levelMaxExperience : int;			/* The experience required to obtain a new level*/

function Update() {
}

/* On awaking the class calls the Set maxXP and UpdateStats methods in order to set the gameobject's
 * MaxExperience and update its (optional) stats according to its starting level 
 */
function Awake() {
	SetMaxXP();
	UpdateStats();
	
}

/* The GainXP function increases the experience and calls the LevelUp method once the experience
 * reaches the experience required to obtain a new level. Any remaining experience is carried over to the next level
 * and can possibly trigger a new LevelUp untill no remaining experience is left.
 *
 * The amount parameter is the amount of experience that should be added to the current amount
 */
function GainXP(amount : int) {
	
	/* When gaining experience a particle effect will be spawned as long as one is assigned */
	if(xpParticles) {
		/* No particles will be spawned when there is already a similar effect */
		if(!transform.Find(xpParticles.name + "(Clone)")) {
			/* The particle effect will be spawned at the gameobject's position and it's transform will be childed to the gameobject */
			var xpParticles : GameObject = Instantiate(xpParticles, transform.localPosition, transform.localRotation);
			xpParticles.transform.parent = transform;
		}
	}
	else {
		Debug.Log("There is no particle system assigned for gaining XP");
	}
	
	/* Adds the amount to the current experience amount as long as a new level isn't reached */
	if(experience + amount < levelMaxExperience) {
		experience += amount;
	}
	/* When a new level will be reached, the remaining experience will be carried to the next level */
	else {
		var tempXP : int = (experience + amount - levelMaxExperience);
		LevelUp();
		GainXP(tempXP);
	}
}

/* The LevelUp function increases the level by one and resets the experience amount
 * A sound and particle effect will also be displayed
 * The experience required to obtain the next level will be set by the SetMaxXP method
 * When leveling up the UpdateStats method will also be called. 
 */
function LevelUp() {
	/* Increases the level by one and resets the experience */
	level ++;
	experience = 0;
	
	/* The setMaxXP sets the new experience required to reach the next level
	 * If the level curve is below zero it is useless to call the method since there will be no level curve
	 */
	if(levelCurve > 1) {
	SetMaxXP();
	}
	
	/* The updateStats method sets new values for any stats the gameobject might have */
	UpdateStats();

	/* When leveling, a particle system will be spawned for a graphical effect to the user, as long as a particle system is assigned */
	if(levelUpParticles) {
		/* No particle effect will be displayed when there is already one in progress */
		if(!transform.Find(levelUpParticles.name+"(Clone)")) {
			/* The particle system will be spawned at the gameobject's position and will be childed to its transform */
			var lUParticles : GameObject = Instantiate(levelUpParticles, transform.localPosition, transform.localRotation);
			lUParticles.transform.parent = transform;
		}
	}
	else {
		Debug.Log("There is no particle emmiter set up for a level up effect");
	}
}

/* The UpdateStats method checks if the gameobject has a CharacterStats component attached, if so, it calls the methods
 * required to increase it's stats according to the level tracked in this class
 */
function UpdateStats() {
	var charStats : Component;
	charStats = gameObject.GetComponent(CharacterStats);

	if(charStats) {
		charStats.UpdateStats(level);
	}
}

/* This function increases the experience required to reach a new level
 * The new experience goal (levelMaxExperience) is calculated by multiplying
 * the base experience with the levelCurve to the power of level.
 *
 * Formula : levelBaseExperience * levelCurve^level
 */
function SetMaxXP() {
	levelMaxExperience = levelMaxExperienceBase * Mathf.Pow(levelCurve, level);
}
